home *** CD-ROM | disk | FTP | other *** search
/ FM Towns: Free Software Collection 11 / FM Towns Free Software Collection 11.iso / t_os / lib / yotpin / src / mosaic.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-09-01  |  10.6 KB  |  475 lines

  1. /*
  2. *    Yamana's Otomeza Plug-in Tool
  3. *        モザイク
  4. *    
  5. *    1995.07.30    乙女座へ移植
  6. *    1995.08.13    点モード追加
  7. *    
  8. *    
  9. */
  10. #include    "otome_pi.h"
  11.  
  12. const char longname[]  = "EFFECT: モザイク";
  13. int            cnfg_max = 3;
  14. PI_CNFG        cnfg[] =
  15.             {    /* 1234567890123456 ,min,max,def,set */
  16.                 { "速い 高品位?  丸", 0,   2,  0,  0 },
  17.                 { "横サイズ"        , 1,  16,  4,  4 },
  18.                 { "縦サイズ"        , 1,  16,  4,  4 },
  19.             };
  20.  
  21. #define    USE_ENV        PI_SET_ENV
  22. #define    USE_TYPE    PI_EFFC_ALORSL
  23. #include    "otome_pi.c"
  24.  
  25. /********************************/
  26.  
  27. void set_vramWidth( vramWidth, xs, pix )
  28. int     *vramWidth;
  29. int     xs,pix;
  30. {
  31.          if( pix < 8 )    *vramWidth = (xs+7)& 0xfff8;
  32.     else if( pix ==8 )    *vramWidth = (xs  );
  33.     else if( pix > 8 )    *vramWidth = (xs*2);
  34. }
  35.  
  36. /********************************/
  37.  
  38. void MosaicEasy( buf, fr, xs,ys )
  39. char    *buf;
  40. FRAME    *fr;
  41. int     xs,ys;
  42. {
  43.     struct
  44.         {    char    *addr;
  45.             short    ds;
  46.             short    sx,sy,ex,ey;
  47.             short    xs,ys;
  48.         }para;
  49.     
  50.     para.addr= buf;
  51.     para.ds  = pi_data->ds;
  52.     para.sx  = fr->lupx;
  53.     para.sy  = fr->lupy;
  54.     para.ex  = fr->rdwx;
  55.     para.ey  = fr->rdwy;
  56.     para.xs  = xs;
  57.     para.ys  = ys;
  58.     EGB_getBlockZoom( EgbPtr, ¶ );
  59.     EGB_putBlockZoom( EgbPtr, 0x00, ¶ );
  60. }
  61.  
  62. /********************************/
  63.  
  64. int     getFunc16( x,y )
  65. int     x,y;
  66. {
  67.     return (pi_imge->image[ (x>>1) + y*(pi_imge->size.x>>1) ]
  68.             >>((x & 1)? 4:0)& 0x0f );
  69. }
  70. int     getFunc256( x,y )
  71. int     x,y;
  72. {
  73.     return (pi_imge->image[ x + y*(pi_imge->size.x) ])& 0xff;
  74. }
  75. /********************************/
  76.  
  77. #define    swap(a,b)\
  78.     {    int     tmp;\
  79.         tmp=(a);(a)=(b);(b)=tmp;\
  80.     }
  81.  
  82. #define    TILE_XS        8
  83. #define    TILE_YS        2
  84. #define    TILE_X        (TILE_XS/8)
  85. #define    TILE_Y        TILE_YS
  86.  
  87. #define    TILEPAT1        8
  88. #define    TILEPAT2        4
  89. #define    USE_TILE        0x40
  90. #define    NOT_USE_TILE    0x20
  91.  
  92. void MosaicNormal( image,buf, fr, xs,ys, xsize,ysize, allsize, pix )
  93. char    *image;
  94. unsigned int     *buf;
  95. FRAME    *fr;
  96. int     xs,ys,xsize,ysize,pix;
  97. POINT    *allsize;
  98. {
  99.     unsigned int     *hist = &buf[ xsize*ysize ];
  100.     int     sx,sy,x,y,i,j;
  101.     int     pos;
  102.     int     mx,my,ch;
  103.     FRAME    Box;
  104.     int     h1,h2;
  105.     char    tile[ 32*32 ];
  106.     int     tilepat[] = { 0, 2, 4, 6,
  107.                             9,11,13,15 };
  108.     int     (*getpix)();
  109.     
  110.     if( pix==8 )    getpix = getFunc256;
  111.             else    getpix = getFunc16;
  112.     
  113.     for( sy=0; sy<ys ; sy+= ysize )
  114.     {    for( sx=0; sx<xs ; sx+= xsize )
  115.         {    
  116.             MOS_rdpos( &ch, &mx, &my );
  117.             if( ch & MOS_RIGHT )    return;
  118.             
  119.             /* 色番号のヒストグラムを作る */
  120.             h1=h2=(-1);
  121.             
  122.             for( y=0; y<ysize; y++ )
  123.             {    for( x=0; x<xsize; x++ )
  124.                 {
  125.                     pos = x+y*xsize;
  126.                     buf [ pos ] = getpix( fr->lupx+sx+x, fr->lupy+sy+y );
  127.                     hist[ pos ] = 0;
  128.                     
  129.                     for( i=0; i<=pos ; i++ )
  130.                     {    if( buf [i] == buf[pos] )    /* 同じ色? */
  131.                         {    hist[i]++;
  132.                             if( hist[i]>=hist[h1] )    /* 頻度の多い2色 */
  133.                                 h2=h1, h1=i;
  134.                             break;
  135.                         }
  136.                     }
  137.                 }
  138.             }
  139.             
  140.             if( h1<0 )    h1 = 0;        /* 全部違う色のときは、何色でもいい! */
  141.             if( h2<0 )    h2 = 1;        /* てきとーに処理するべし(^^;) */
  142.             
  143.             if( hist[h1] > hist[h2]*3+1 )
  144.             {    
  145.                 EGB_paintMode( EgbPtr, NOT_USE_TILE );
  146.                 EGB_color( EgbPtr, EGB_PAINTCOL, buf[h1] );
  147.             }
  148.             else    /* タイルパターンを作る */
  149.             {    j=0;
  150.                 if( hist[h1]==hist[h2] )    /* 頻度比 1:1 は市松模様 */
  151.                 {    pos = TILEPAT1;
  152.                     
  153.                     /* タイルが汚くならないよう色番号によって位置を決める */
  154.                     if( buf[h1]&1 )
  155.                     {    if( buf[h2]&1 )
  156.                         {    if( h1>=h2 )    swap( h1,h2 );
  157.                         }else
  158.                             swap( h1,h2 );
  159.                     }/* この処理、はっきり言っていい加減である(^^;) */
  160.                     
  161.                 }else
  162.                 {    pos = TILEPAT2;            /* 頻度比 1:3 */
  163.                     
  164.                     /* タイル開始位置をずらす */
  165.                     if( buf[h1]&1 )
  166.                     {    if( buf[h2]&1 )
  167.                         {    if( h1>=h2 )    j=1;
  168.                         }else
  169.                             j=1;
  170.                     }
  171.                 }
  172.                 
  173.                 if( pix == 8 )
  174.                 {    for(i=0; i<TILE_XS*TILE_YS; i++ )
  175.                         tile[i] = buf[h1];
  176.                     for( i=0; i<pos ;i++ )
  177.                         tile[ tilepat[i]+j ] = buf[h2];
  178.                 }else
  179.                 {    for(i=0; i<TILE_XS*TILE_YS; i++ )
  180.                         tile[i] = (buf[h1]& 0x0f) | (buf[h1]<<4) ;
  181.                     for( i=0; i<pos ;i++ )
  182.                     {    x = (tilepat[i]+j)>>1;
  183.                         if( (tilepat[i]+j) & 1 )
  184.                             tile[x] = (tile[x] & 0x0f) | (buf[h2]<<4) ;
  185.                         else
  186.                             tile[x] = (tile[x] & 0xf0) | (buf[h2]) ;
  187.                     }
  188.                 }
  189.                 
  190.                 EGB_paintMode  ( EgbPtr, USE_TILE );
  191.                 EGB_tilePattern( EgbPtr, EGB_PAINTCOL,TILE_X,TILE_Y, tile );
  192.             }
  193.             
  194.             Box.lupx = fr->lupx + sx;
  195.             Box.lupy = fr->lupy + sy;
  196.             Box.rdwx = Box.lupx + xsize-1 ;
  197.             Box.rdwy = Box.lupy + ysize-1 ;
  198.             EGB_rectangle( EgbPtr, &Box );
  199.             
  200.         }
  201.     }
  202.     
  203. }
  204.  
  205.  
  206. void MosaicPoint( image,buf, fr, xs,ys, xsize,ysize, allsize, pix )
  207. char    *image;
  208. unsigned int     *buf;
  209. FRAME    *fr;
  210. int     xs,ys,xsize,ysize,pix;
  211. POINT    *allsize;
  212. {
  213.     unsigned int     *hist = &buf[ xsize*ysize ];
  214.     int     sx,sy,x,y,i,j;
  215.     int     pos;
  216.     int     mx,my,ch;
  217.     FRAME    Box;
  218.     int     h1,h2;
  219.     char    tile[ 32*32 ];
  220.     int     tilepat[] = { 0, 2, 4, 6,
  221.                             9,11,13,15 };
  222.     int     (*getpix)();
  223.     
  224.     if( pix==8 )    getpix = getFunc256;
  225.             else    getpix = getFunc16;
  226.     
  227.     for( sy=0; sy<ys ; sy+= ysize )
  228.     {    for( sx=0+(sy % (ysize*2))/2 ; sx<xs ; sx+= xsize )
  229.         {    
  230.             MOS_rdpos( &ch, &mx, &my );
  231.             if( ch & MOS_RIGHT )    return;
  232.             
  233.             /* 色番号のヒストグラムを作る */
  234.             h1=h2=(-1);
  235.             for( y=0; y<ysize; y++ )
  236.             {    for( x=0; x<xsize; x++ )
  237.                 {
  238.                     pos = x+y*xsize;
  239.                     buf [ pos ] = getpix( fr->lupx+sx+x, fr->lupy+sy+y );
  240.                     hist[ pos ] = 0;
  241.                     
  242.                     for( i=0; i<=pos ; i++ )
  243.                     {    if( buf [i] == buf[pos] )    /* 同じ色? */
  244.                         {    hist[i]++;
  245.                             if( hist[i]>=hist[h1] )    /* 頻度の多い2色 */
  246.                                 h2=h1, h1=i;
  247.                             break;
  248.                         }
  249.                     }
  250.                 }
  251.             }
  252.             
  253.             EGB_paintMode( EgbPtr, NOT_USE_TILE );
  254.             EGB_color( EgbPtr, EGB_PAINTCOL, PI_BACKCOL );
  255.             Box.lupx = fr->lupx + sx;
  256.             Box.lupy = fr->lupy + sy;
  257.             Box.rdwx = Box.lupx + xsize-1 ;
  258.             Box.rdwy = Box.lupy + ysize-1 ;
  259.             EGB_rectangle( EgbPtr, &Box );
  260.             
  261.             if( h1<0 )    h1 = 0;        /* 全部違う色のときは、何色でもいい! */
  262.             if( h2<0 )    h2 = 1;        /* てきとーに処理するべし(^^;) */
  263.             
  264.             if( hist[h1] > hist[h2]*3+1 )
  265.             {    
  266.                 EGB_paintMode( EgbPtr, NOT_USE_TILE );
  267.                 EGB_color( EgbPtr, EGB_PAINTCOL, buf[h1] );
  268.             }
  269.             else    /* タイルパターンを作る */
  270.             {    j=0;
  271.                 if( hist[h1]==hist[h2] )    /* 頻度比 1:1 は市松模様 */
  272.                 {    pos = TILEPAT1;
  273.                     
  274.                     /* タイルが汚くならないよう色番号によって位置を決める */
  275.                     if( buf[h1]&1 )
  276.                     {    if( buf[h2]&1 )
  277.                         {    if( h1>=h2 )    swap( h1,h2 );
  278.                         }else
  279.                             swap( h1,h2 );
  280.                     }/* この処理、はっきり言っていい加減である(^^;) */
  281.                     
  282.                 }else
  283.                 {    pos = TILEPAT2;            /* 頻度比 1:3 */
  284.                     
  285.                     /* タイル開始位置をずらす */
  286.                     if( buf[h1]&1 )
  287.                     {    if( buf[h2]&1 )
  288.                         {    if( h1>=h2 )    j=1;
  289.                         }else
  290.                             j=1;
  291.                     }
  292.                 }
  293.                 
  294.                 if( pix == 8 )
  295.                 {    for(i=0; i<TILE_XS*TILE_YS; i++ )
  296.                         tile[i] = buf[h1];
  297.                     for( i=0; i<pos ;i++ )
  298.                         tile[ tilepat[i]+j ] = buf[h2];
  299.                 }else
  300.                 {    for(i=0; i<TILE_XS*TILE_YS; i++ )
  301.                         tile[i] = (buf[h1]& 0x0f) | (buf[h1]<<4) ;
  302.                     for( i=0; i<pos ;i++ )
  303.                     {    x = (tilepat[i]+j)>>1;
  304.                         if( (tilepat[i]+j) & 1 )
  305.                             tile[x] = (tile[x] & 0x0f) | (buf[h2]<<4) ;
  306.                         else
  307.                             tile[x] = (tile[x] & 0xf0) | (buf[h2]) ;
  308.                     }
  309.                 }
  310.                 
  311.                 EGB_paintMode  ( EgbPtr, USE_TILE );
  312.                 EGB_tilePattern( EgbPtr, EGB_PAINTCOL,TILE_X,TILE_Y, tile );
  313.             }
  314.             
  315.             Box.lupx = fr->lupx + sx + xsize/2-1 ;
  316.             Box.lupy = fr->lupy + sy + ysize/2-1 ;
  317.             Box.rdwx = xsize/2;
  318.             Box.rdwy = ysize/2;
  319.             EGB_ellipse( EgbPtr, &Box );
  320.             
  321.         }
  322.     }
  323.     
  324. }
  325.  
  326.  
  327.  
  328. /* 32K色だと楽だな~ */
  329.  
  330. void MosaicNormal32K( image, mode, fr, xs,ys, xsize,ysize, allsize )
  331. char    *image;
  332. int     mode;
  333. FRAME    *fr;
  334. int     xs,ys,xsize,ysize;
  335. POINT    *allsize;
  336. {
  337.     int     sx,sy,x,y, ss;
  338.     int     pos,tmp;
  339.     int     mx,my,ch;
  340.     FRAME    Box;
  341.     unsigned int     r,g,b;
  342.     
  343. //    clock_t    t;
  344. //    t=clock();
  345.     
  346.     for( ss=0,sy=0; sy<ys ; sy+= ysize )
  347.     {
  348.         if( mode==2 )    ss = (sy % (ysize*2))/2;
  349.         for( sx=0+ss ; sx<xs ; sx+= xsize )
  350.         {    
  351.             MOS_rdpos( &ch, &mx, &my );
  352.             if( ch & MOS_RIGHT )    return;
  353.             
  354.             r=g=b=0;
  355.             for( y=0; y<ysize; y++ )
  356.             {    for( x=0; x<xsize; x++ )
  357.                 {    
  358.                     pos = ((fr->lupx + sx + x)<<1 )
  359.                              + (fr->lupy + sy + y)*(allsize->x<<1) ;
  360.                     
  361.                     tmp = image[ pos ] + (image[ pos+1 ]<<8) ;
  362.                     g += ((tmp>>10) & 0x1f);
  363.                     r += ((tmp>>5 ) & 0x1f);
  364.                     b += ((tmp    ) & 0x1f);
  365.                 }
  366.             }
  367.             pos = xsize*ysize;
  368.             g /= pos;
  369.             r /= pos;
  370.             b /= pos;
  371.             EGB_paintMode( EgbPtr, NOT_USE_TILE );
  372.             
  373.             Box.lupx = fr->lupx + sx;
  374.             Box.lupy = fr->lupy + sy;
  375.             Box.rdwx = Box.lupx + xsize-1 ;
  376.             Box.rdwy = Box.lupy + ysize-1 ;
  377.             
  378.             if( mode == 1 )
  379.             {    EGB_color( EgbPtr, EGB_PAINTCOL, (int)(g<<10 | r<<5 | b ));
  380.                 EGB_rectangle( EgbPtr, &Box );
  381.             }else
  382.             {    EGB_color( EgbPtr, EGB_PAINTCOL, PI_BACKCOL );
  383.                 EGB_rectangle( EgbPtr, &Box );
  384.                 EGB_color( EgbPtr, EGB_PAINTCOL, (int)(g<<10 | r<<5 | b ));
  385.                 
  386.                 Box.lupx = fr->lupx + sx + xsize/2-1 ;
  387.                 Box.lupy = fr->lupy + sy + ysize/2-1 ;
  388.                 Box.rdwx = xsize/2;
  389.                 Box.rdwy = ysize/2;
  390.                 EGB_ellipse( EgbPtr, &Box );
  391.             }
  392.         }
  393.     }
  394.     
  395. //    printf("time = %d", clock()-t );
  396.     
  397.     /* EGB_point : clock==850 */
  398.     /* 直接取る  : clock==305 */
  399. }
  400.  
  401. /********************************/
  402.  
  403. int APL_exec()
  404. {
  405.     int     mode,xsize,ysize;
  406.     int     width,height, xs,ys,vramWidth;
  407.     char    *buf;
  408.     int     mx,my,ch;
  409.     FRAME    fr;
  410.     
  411.     mode  = cnfg[0].val;        /* 0:高速版 1:高品位版 2:点 */
  412.     xsize = cnfg[1].val;        /* Xサイズ */
  413.     ysize = cnfg[2].val;        /* Yサイズ */
  414.     
  415.     if( xsize == 1 && ysize == 1 )    return NOERR;
  416.     
  417.     memcpy( &fr, g_para, sizeof( fr ) );
  418.     
  419.     EGB_writePage( EgbPtr, pi_imge->page );
  420.     EGB_viewport ( EgbPtr, &fr );
  421.     
  422.     fr.lupx = (fr.lupx / xsize * xsize);
  423.     fr.lupy = (fr.lupy / ysize * ysize);
  424.     fr.rdwx = (fr.rdwx / xsize * xsize + xsize-1);
  425.     fr.rdwy = (fr.rdwy / ysize * ysize + ysize-1);
  426.     
  427.     width  = (fr.rdwx - fr.lupx + 1);
  428.     height = (fr.rdwy - fr.lupy + 1);
  429.     xs = (width +xsize-1)/xsize ;
  430.     ys = (height+ysize-1)/ysize ;
  431.     
  432.     /*******************************/
  433.     if( mode == 0 )
  434.     {
  435.         set_vramWidth( &vramWidth, xs, pi_imge->pix );
  436.         
  437.         if( (buf = PI_MALLOC( vramWidth*ys ))==NULL )
  438.             return PI_ERROR_NO_MEMORY;
  439.         
  440.         MosaicEasy( buf, &fr, xs,ys );
  441.         
  442.         PI_FREE( buf );
  443.     }
  444.     else
  445.     {    xs *= xsize;
  446.         ys *= ysize;
  447.         
  448.         if( pi_imge->pix >8 )
  449.         {
  450.             MosaicNormal32K( pi_imge->image, mode,
  451.                     &fr, xs,ys, xsize,ysize, &pi_imge->size );
  452.         }
  453.         else
  454.         {    if( (buf = PI_MALLOC( xsize*ysize*sizeof(int)*2 ))==NULL )
  455.                 return PI_ERROR_NO_MEMORY;
  456.             
  457.             if( mode ==1 )
  458.                 MosaicNormal( pi_imge->image, (unsigned int*)buf,
  459.                     &fr, xs,ys, xsize,ysize, &pi_imge->size, pi_imge->pix );
  460.             else
  461.                 MosaicPoint( pi_imge->image, (unsigned int*)buf,
  462.                     &fr, xs,ys, xsize,ysize, &pi_imge->size, pi_imge->pix );
  463.             
  464.             PI_FREE( buf );
  465.         }
  466.     }
  467.     
  468.     do
  469.     {    MOS_rdpos( &ch, &mx, &my );
  470.     }while( ch & MOS_RIGHT );
  471.     
  472.     
  473.     return NOERR;
  474. }
  475.